/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package provider.impl.coalescent;

import coalescent.data.K69Data.StringK69Data;
import coalescent.model.K69;

import commons.provider.ProviderException;
import commons.provider.impl.BaseXMLFileBasedProviderImpl;

import org.dom4j.Element;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Susanta Tewari
 * @history First created on Apr 12, 2012
 */
public class Providerimpls {

    /**
     * Class description
     *
     *
     * @version        Enter version here..., 12/10/09
     * @author         Susanta Tewari
     */
    public static class K69XMLDataProviderImpl extends BaseXMLFileBasedProviderImpl<StringK69Data>
            implements coalescent.provider.Providers.StringK69DataProviderFileBased {

        /**
         * Method description
         *
         *
         * @param root
         *
         * @return
         *
         * @throws ProviderException
         */
        @Override
        protected StringK69Data createFromRootElement(Element root) throws ProviderException {


            // get mutation
            Double theta = Double.valueOf(root.elementText("theta"));


            // 4. get 'allele' elements from the root
            @SuppressWarnings("unchecked") List<Element> alleles = root.elements("allele");


            // 5. count the # of sites
            int sitesCount = alleles.get(0).elementText("sequence").length();


            // 6. prepare data for GtArrayK69Data
            // 6.3 holder of allele frequency for each allele sequence
            Map<String, Integer> alleleFreq = new HashMap<>(alleles.size());


            // 7. get elements 'label', 'sequence' and 'frequency' from the 'allele' element
            for (Element allele : alleles) {

                String allele_label = allele.attributeValue("label");
                String sequence     = allele.elementText("sequence");
                Integer frequency   = Integer.valueOf(allele.elementText("frequency"));


                // 5.1 check the invariant: all sequences have the same number of sites
                if (sequence.length() != sitesCount) {

                    throw new java.security.ProviderException(
                        "Sites count does not match for allele " + allele_label);
                }

                alleleFreq.put(sequence, frequency);
            }

            try {
                return new StringK69Data(new K69(theta), alleleFreq);
            } catch (IllegalArgumentException ex) {
                throw new ProviderException("Data integrity error", ex);
            }
        }

        /**
         * Method description
         *
         *
         * @return
         */
        @Override
        public Class<K69> getModelClass() {
            return K69.class;
        }

        /**
         * Method description
         *
         *
         * @return
         */
        @Override
        public Class<StringK69Data> getDataClass() {
            return StringK69Data.class;
        }
    }
}
